﻿namespace MVCResourceEngine
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;
    using System.Web.Routing;

    /// <summary>
    /// Represents a collection of resource engines that are available to the application.
    /// </summary>
    public class ResourceEngineCollection : Collection<IResourceEngine>
    {
        /// <summary>
        /// Finds the resource.
        /// </summary>
        /// <param name="requestContext">The request context.</param>
        /// <param name="resourceName">Name of the resource.</param>
        /// <returns>The resource engine result</returns>
        public virtual ResourceEngineResult FindResource(RequestContext requestContext, string resourceName)
        {
            // throw exception if request context is null
            if (requestContext == null)
            {
                throw new ArgumentNullException("requestContext");
            }

            // throw exception if resource name is null or empty
            if (string.IsNullOrEmpty(resourceName))
            {
                throw new ArgumentException("resourceName cannot be null or empty.", "resourceName");
            }

            // try to find resource from each resource engine by cache
            foreach (var resourceEngineResult in this.Items.Select(resourceEngine => resourceEngine.FindResource(requestContext, resourceName, true)).Where(resourceEngineResult => resourceEngineResult.Resource != null))
            {
                return resourceEngineResult;
            }

            // instanciate new list of searched locations
            var searchedLocations = new List<string>();

            // try to find resource from each resource engine
            foreach (var resourceEngineResult in this.Items.Select(resourceEngine => resourceEngine.FindResource(requestContext, resourceName, false)))
            {
                // return resurce engine result if it is not null
                if (resourceEngineResult.Resource != null)
                {
                    return resourceEngineResult;
                }

                // add searched locations to list
                searchedLocations.AddRange(resourceEngineResult.SearchedLocations);
            }

            // return list of searched locations
            return new ResourceEngineResult(searchedLocations);
        }

    }
}
